package com.adlotto2.android.util;

import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.ref.WeakReference;
import java.util.HashMap;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;

import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.net.http.AndroidHttpClient;
import android.os.AsyncTask;
import android.view.View;
import android.widget.ImageView;
import android.widget.ProgressBar;

import com.adlotto2.android.common.LottoAdFullActivity;

public class LottoAdImageDownloader {
	public static final int IMGAE_CACHE_LIMIT_SIZE = 50;
	public static HashMap<String, Bitmap> mImageCache = new HashMap<String, Bitmap>();
	
	public enum Mode { NO_ASYNC_TASK, NO_DOWNLOADED_DRAWABLE, CORRECT }
    private Mode mode = Mode.NO_ASYNC_TASK;

	private Context mContext = null;
	private Resources resources = null;
	public Drawable loadingImage = null;
	public Drawable failImage = null;

	public LottoAdImageDownloader(Context context) {
		this.mContext = context;
		this.resources = (context == null ? null : context.getResources());
	}

	public void setLoadingImage(int resId) {
		this.loadingImage = (this.resources == null ? null : this.resources
				.getDrawable(resId));
	}

	public void setFailImage(int resId) {
		this.failImage = (this.resources == null ? null : this.resources
				.getDrawable(resId));
	}

	/*
	 * 캐쉬되어 있는 이미지를 삭제한다.
	 * @param	[IN] url: 검색할 이미지
	 * @return	-
	 */
	public void deleteCachedImage(String url) {
		Bitmap cachedImage = mImageCache.get(url);
		if(cachedImage != null) {
			cachedImage.recycle();
		}
	}
	
	public void download(String url, ImageView imageView, int position, ProgressBar progressBar) {
		Bitmap cachedImage = mImageCache.get(url);
		if (cachedImage != null && cachedImage.isRecycled() == false) {
			imageView.setImageBitmap(cachedImage);
			if(progressBar != null)
				progressBar.setVisibility(View.GONE);
			
			if(mContext.getClass().getSimpleName().equals("LottoAdFullActivity")){
				((LottoAdFullActivity)mContext).threadStart();
			}
			
		} else if (cancelPotentialDownload(url, imageView)) {
			if (mImageCache.size() > IMGAE_CACHE_LIMIT_SIZE) {
				mImageCache.clear();
			}
			
			progressBar.setVisibility(View.VISIBLE);

			CNImageDownloaderTask task = new CNImageDownloaderTask(url,
					imageView,position,progressBar);
			DownloadedDrawable downloadedDrawable = new DownloadedDrawable(task);
			imageView.setImageDrawable(downloadedDrawable);
			task.execute(url);
		}
	}

	private static boolean cancelPotentialDownload(String url,
			ImageView imageView) {
		CNImageDownloaderTask bitmapDownloaderTask = getBitmapDownloaderTask(imageView);

		if (bitmapDownloaderTask != null) {
			String bitmapUrl = bitmapDownloaderTask.url;
			if ((bitmapUrl == null) || (!bitmapUrl.equals(url))) {
				bitmapDownloaderTask.cancel(true);
			} else {
				return false;
			}
		}
		return true;
	}

	public void setFailedImage(ImageView imageView) {
		if (imageView != null) {
			imageView.setImageDrawable(this.failImage);
			// imageView.setAdjustViewBounds(true);
		}
	}

	public void setLoadingImage(ImageView imageView) {
		if (imageView != null) {
			imageView.setImageDrawable(this.loadingImage);
		}
	}

	private static CNImageDownloaderTask getBitmapDownloaderTask(
			ImageView imageView) {
		if (imageView != null) {
			Drawable drawable = imageView.getDrawable();
			if (drawable instanceof DownloadedDrawable) {
				DownloadedDrawable downloadedDrawable = (DownloadedDrawable) drawable;
				return downloadedDrawable.getBitmapDownloaderTask();
			}
		}
		return null;
	}

	class DownloadedDrawable extends BitmapDrawable {
		private final WeakReference<CNImageDownloaderTask> bitmapDownloaderTaskReference;

		public DownloadedDrawable(CNImageDownloaderTask bitmapDownloaderTask) {
			this.bitmapDownloaderTaskReference = new WeakReference<CNImageDownloaderTask>(
					bitmapDownloaderTask);
		}

		public CNImageDownloaderTask getBitmapDownloaderTask() {
			return bitmapDownloaderTaskReference.get();
		}

		@Override
		public void draw(Canvas canvas) {
			if (LottoAdImageDownloader.this.loadingImage != null) {
				LottoAdImageDownloader.this.loadingImage.setBounds(canvas
						.getClipBounds());
				LottoAdImageDownloader.this.loadingImage.draw(canvas);
			}
		}

		public int getOpacity() {
			return 0;
		}

		public void setAlpha(int alpha) {
		}

		@Override
		public void setColorFilter(ColorFilter cf) {
		}
	}

	class CNImageDownloaderTask extends AsyncTask<String, Void, Bitmap> {
		public String url;
		public String targetUrl;
		public int position;
		public ProgressBar mProgressBar;
		private WeakReference<ImageView> imageViewReference;

		public CNImageDownloaderTask(String url, ImageView imageView,int position,ProgressBar progressbar) {
			this.targetUrl = url;
			this.position = position;
			this.mProgressBar = progressbar;
			this.imageViewReference = new WeakReference<ImageView>(imageView);
		}

		@Override
		protected Bitmap doInBackground(String... params) {
			Bitmap bitmap = downloadBitmap(params[0]); 
			if(bitmap != null){
//			ApplicationUtils.addBitmapToMemoryCache(mContext, String.valueOf(params[0]), bitmap);
			}
			return bitmap;
		}

		@Override
		protected void onPostExecute(Bitmap bitmap) {
			if (isCancelled()) {
				bitmap = null;
			}

			if (imageViewReference != null) {
				ImageView imageView = imageViewReference.get();
				CNImageDownloaderTask bitmapDownloaderTask = getBitmapDownloaderTask(imageView);

				if (this == bitmapDownloaderTask) {
					if (bitmap != null) {
						LottoAdImageDownloader.mImageCache.put(targetUrl, bitmap);
						imageView.setImageBitmap(bitmap);
					} else
						LottoAdImageDownloader.this.setFailedImage(imageView);
					// imageView.setImageResource(R.drawable.noimage);
					if(mProgressBar != null)
						mProgressBar.setVisibility(View.GONE);
					
					if(!mProgressBar.isShown()){
						if(mContext.getClass().getSimpleName().equals("LottoAdFullActivity")){
							((LottoAdFullActivity)mContext).threadStart();
						}
					}
				}
			}
		}

		private CNImageDownloaderTask getBitmapDownloaderTask(
				ImageView imageView) {
			if (imageView != null) {
				Drawable drawable = imageView.getDrawable();
				if (drawable instanceof DownloadedDrawable) {
					DownloadedDrawable downloadedDrawable = (DownloadedDrawable) drawable;
					return downloadedDrawable.getBitmapDownloaderTask();
				}
			}
			return null;
		}

		private Bitmap downloadBitmap(String url) {
			final HttpClient client			= (mode == Mode.NO_ASYNC_TASK) ? 
		    		new DefaultHttpClient() : AndroidHttpClient.newInstance("Android");
		    		
		    final HttpGet getRequest 		= new HttpGet(url);
		    
		    try 
		    {
		        HttpResponse response = client.execute(getRequest);
		        final int statusCode = response.getStatusLine().getStatusCode();
		        
		        if (statusCode != HttpStatus.SC_OK) 
		        {
		            return null;
		        }

		        final HttpEntity entity = response.getEntity();
		        
		        if (entity != null) 
		        {
		            InputStream inputStream = null;
		            try {
		            	inputStream = entity.getContent();
		            	final Bitmap bitmap = BitmapFactory.decodeStream(new FlushedInputStream(inputStream));
		            	return bitmap;
		            } catch (Exception e) {
						return null;
					} finally {
		                if (inputStream != null) 
		                {
		                    inputStream.close();
		                }
		                
		                entity.consumeContent();
		            }
		        }
		    } 
		    catch (IOException e) 
		    {
		        getRequest.abort();
		    } 
		    catch (IllegalStateException e) 
		    {
		        getRequest.abort();
		    } 
		    catch (Exception e) 
		    {
		        getRequest.abort();
		    } 
		    finally 
		    {
		        if ((client instanceof AndroidHttpClient)) 
		        {
		            ((AndroidHttpClient)client).close();
		        }
		    }
		    
		    return null;
		}
	}
	
//	protected Bitmap toGrayScale(Bitmap bitmap, int width, int height) {
//		Bitmap grayBmp = Bitmap.createBitmap(width, height,
//				Bitmap.Config.RGB_565);
//		Canvas c = new Canvas(grayBmp);
//		Paint p = new Paint();
//
//		ColorMatrix cm = new ColorMatrix(new float[] { 0.5f, 0.5f, 0.5f, 0, 0,
//				0.5f, 0.5f, 0.5f, 0, 0, 0.5f, 0.5f, 0.5f, 0, 0, 0, 0, 0, 1, 0,
//				0, 0, 0, 0, 0, 1, 0 });
//		cm.setSaturation(0);
//		ColorMatrixColorFilter f = new ColorMatrixColorFilter(cm);
//		p.setColorFilter(f);
//		c.drawBitmap(bitmap, 0, 0, p);
//		bitmap.recycle();
//		bitmap = grayBmp;
//		return grayBmp;
//	}

	static class FlushedInputStream extends FilterInputStream {
		public FlushedInputStream(InputStream inputStream) {
			super(inputStream);
		}

		@Override
		public long skip(long n) throws IOException {
			long totalBytesSkipped = 0L;
			while (totalBytesSkipped < n) {
				long bytesSkipped = in.skip(n - totalBytesSkipped);
				if (bytesSkipped == 0L) {
					int bytes = read();
					if (bytes < 0) {
						break; // we reached EOF
					} else {
						bytesSkipped = 1; // we read one byte
					}
				}
				totalBytesSkipped += bytesSkipped;
			}
			return totalBytesSkipped;
		}
	}
}